package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net/http"
	"sen-golang-study/go_game_study/hero_story_go_server/common"
	"sen-golang-study/go_game_study/hero_story_go_server/game_server/internal/infrastructure/config"
	"sen-golang-study/go_game_study/hero_story_go_server/game_server/internal/infrastructure/database"
	"sen-golang-study/go_game_study/hero_story_go_server/game_server/internal/infrastructure/registry"
	"sen-golang-study/go_game_study/hero_story_go_server/game_server/internal/interfaces/container"
	"time"

	clientv3 "go.etcd.io/etcd/client/v3"
)

var (
	serverID   = flag.Uint("server_id", 3001, "当前服务器 Id")
	serverPort = flag.Uint("server_port", 12100, "当前服务器端口号")
)

// 程序参数 -server-id=1001 -listen=127.0.0.1:12345 -responsibilities="GAME,CHAT,LOGIN" -max-connections=1000
func main() {
	flag.Parse()

	// 初始化配置
	config.Init()

	// 初始化数据库
	database.Init()
	defer func() {
		err := database.Close()
		if err != nil {
			log.Printf("Close database failed: %v", err)
		}
	}()

	// 创建依赖注入容器
	appContainer := container.NewContainer()

	// 创建服务注册器
	etcdConfig := config.GetEtcdConfig()
	etcdClient, err := clientv3.New(clientv3.Config{
		Endpoints:   etcdConfig.Endpoints,
		DialTimeout: 5 * time.Second,
	})
	if err != nil {
		log.Fatalf("Failed to create etcd client: %v", err)
	}
	defer func() {
		if closeErr := etcdClient.Close(); closeErr != nil {
			log.Printf("Failed to close etcd client: %v", closeErr)
		}
	}()

	etcdRegistry := registry.NewEtcdRegistry(etcdClient)

	// 注册服务到etcd
	serverConfig := config.GetServerConfig()
	serverInfo := &common.GameServerInfo{
		ServerId:         uint32(*serverID),
		ServiceAddr:      serverConfig.ListenAddr,
		Responsibilities: []common.ServerResponsibility{common.GAME},
		MaxConnections:   1000,
		CurrentLoad:      0,
	}

	serviceKey := fmt.Sprintf("/game_servers/%d", *serverID)
	err = etcdRegistry.Register(context.Background(), serviceKey, serverInfo, 30*time.Second)
	if err != nil {
		log.Fatalf("Failed to register service: %v", err)
	}
	defer func() {
		if registerErr := etcdRegistry.Unregister(context.Background(), serviceKey); registerErr != nil {
			log.Printf("Failed to unregister service: %v", registerErr)
		}
	}()

	// 启动定期更新服务负载的协程
	go loopGrantAndPut(etcdRegistry, serviceKey, serverInfo)

	// 启动会话清理协程
	go loopCleanExpiredSessions(appContainer)

	// 设置HTTP路由
	webSocketHandler := appContainer.GetWebSocketHandler()
	http.HandleFunc("/websocket", webSocketHandler.HandleWebSocket)

	// 启动HTTP服务器
	addr := fmt.Sprintf(":%d", *serverPort)
	log.Printf("Game server starting on %s", addr)
	log.Fatal(http.ListenAndServe(addr, nil))
}

// loopGrantAndPut 定期更新服务负载和注册信息
func loopGrantAndPut(registry *registry.EtcdRegistry, serviceKey string, serverInfo *common.GameServerInfo) {
	ticker := time.NewTicker(10 * time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			// 更新负载信息（这里简单设置为当前时间戳）
			serverInfo.CurrentLoad = uint32(time.Now().Unix() % 1000) // 模拟负载变化

			// 重新注册服务
			err := registry.Register(context.Background(), serviceKey, serverInfo, 30*time.Second)
			if err != nil {
				log.Printf("Failed to update service registration: %v", err)
			}
		}
	}
}

// loopCleanExpiredSessions 定期清理过期会话
func loopCleanExpiredSessions(appContainer *container.Container) {
	ticker := time.NewTicker(60 * time.Second) // 每分钟清理一次
	defer ticker.Stop()

	sessionService := appContainer.GetSessionManagementService()
	timeoutMs := int64(300000) // 5分钟超时

	for {
		select {
		case <-ticker.C:
			err := sessionService.CleanExpiredSessions(timeoutMs)
			if err != nil {
				log.Printf("Failed to clean expired sessions: %v", err)
			}
		}
	}
}
